package com.xayy.mgt.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.kawins.base.result.CheckResult;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.HttpUtil;
import cn.kawins.mybatis.base.BaseServiceImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.xayy.core.constant.BayesArgs;
import com.xayy.mgt.enums.HealthStatu;
import com.xayy.mgt.mapper.BayesMapper;
import com.xayy.mgt.mapper.NodeParamInfoMapper;
import com.xayy.mgt.model.*;
import com.xayy.mgt.model.vo.*;
import com.xayy.mgt.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Nie
 * @version V1.0
 * @date 2023/9/19 10:40
 */
@Service
public class BayesHealthServiceImpl extends BaseServiceImpl<BayesHealth> implements BayesHealthService {

    @Autowired
    private BayesService bayesService;
    @Autowired
    private NodeInfoService nodeInfoService;
    @Autowired
    private BayesHealthRecordService bayesHealthRecordService;
    @Autowired
    private BayesFaultInfoService bayesFaultInfoService;
    @Autowired
    private SystemTelemetryService systemTelemetryService;
    @Autowired
    private NodeParamInfoService nodeParamInfoService;
    @Autowired
    private NodeParamInfoMapper nodeParamInfoMapper;

    @Autowired
    private BayesArgs bayesArgs;

    @Override
    public CheckResult<BayesHealthVo> getNodeHealthInfo(Long satelliteId, Long nodeId) {
        BayesHealth bayesHealth = selectOne(BayesHealth.builder().satelliteId(satelliteId).nodeId(nodeId).build());
        if (BeanUtil.isEmpty(bayesHealth)) {
            // 第一次新建信息
            bayesHealth = new BayesHealth();
            bayesHealth.setSatelliteId(satelliteId);
            bayesHealth.setNodeId(nodeId);
            bayesHealth.setWeight(0D);
            // 插入信息
            insert(bayesHealth);
        }
        BayesHealthVo bayesHealthVo = BeanUtil.copyBean(bayesHealth, BayesHealthVo.class);
        List<BayesFaultInfo> faultInfos = bayesFaultInfoService.select(BayesFaultInfo.builder().parentId(bayesHealth.getId()).type(1).build());
        bayesHealthVo.setFaultList(faultInfos);
        return CheckResult.success(bayesHealthVo);

    }

    @Override
    public CheckResult<Object> updateInfo(BayesHealth bayesHealth) {
        int i = updateById(bayesHealth);
        if (i > 0) {
            return CheckResult.success("修改成功");
        }
        return CheckResult.fail("修改失败");
    }

    @Override
    public CheckResult<Object> getRecordInfo(HealthRecordVo healthRecordVo) {
        if (healthRecordVo.getPageStart() == null || healthRecordVo.getPageSize() == null)
            return CheckResult.fail("页起始数和每页条数不能为空");
        // 获取节点id
        CheckResult<List<Long>> childIds = nodeInfoService.getChildIds(healthRecordVo.getSatelliteId(), healthRecordVo.getNodeId());
        if (childIds.no())
            return CheckResult.fail(childIds.getCheckMsg());
        List<Long> ids = childIds.getData();
        Example example = new Example(BayesHealthRecord.class);
        example.orderBy("healthTime");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("satelliteId", healthRecordVo.getSatelliteId());
        criteria.andIn("nodeId", ids);
        if (BeanUtil.isNotEmpty(healthRecordVo.getTime())) {
            criteria.andLike("healthTime", DateUtil.format(healthRecordVo.getTime(),"yyyy-MM-dd")+"%");
        }
        PageMethod.startPage(healthRecordVo.getPageStart(), healthRecordVo.getPageSize());
        List<BayesHealthRecord> bayesHealthRecords = bayesHealthRecordService.selectByExample(example);
        PageInfo<BayesHealthRecord> bayesHealthPageInfo = new PageInfo<>(bayesHealthRecords);
        return CheckResult.success(bayesHealthPageInfo);
    }

    @Override
    public CheckResult<BayesHealthRecordVo> getRecordInfoById(Long id) {
        BayesHealthRecord bayesHealthRecord = bayesHealthRecordService.selectById(id);
        if (BeanUtil.isEmpty(bayesHealthRecord))
            return CheckResult.fail("评估记录不存在");
        BayesHealthRecordVo bayesHealthRecordVo = BeanUtil.copyBean(bayesHealthRecord, BayesHealthRecordVo.class);
        Example example = new Example(BayesFaultInfo.class);
        example.orderBy("parentId").orderBy("id");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId",bayesHealthRecord.getId());
        criteria.andEqualTo("type",2);
        List<BayesFaultInfo> faultInfos = bayesFaultInfoService.selectByExample(example);
        bayesHealthRecordVo.setFaultList(faultInfos);
        return CheckResult.success(bayesHealthRecordVo);
    }

    @Override
    public CheckResult<Object> componentAssess(ComponentAssessVo assessVo) {
        List<ComponentAssessVo.Weight> weight = assessVo.getWeight();
        if(CollUtil.isEmpty(weight)){
            return CheckResult.fail("权重不能为空");
        }
        long count = weight.stream().filter(f -> {
            String[] split = f.getValue().toString().split("\\.");
            if (split.length > 1) {
                return split[1].length() > 2;
            }
            return false;
        }).count();
        if(count > 0){
            return CheckResult.fail("权重最大保留两位小数");
        }
        int sum = 0;
        for (ComponentAssessVo.Weight w : weight) {
            int num = (int)(w.getValue()*100);
            sum+=num;
        }
        if(sum != 100){
            return CheckResult.fail("权重之和必须为1");
        }
        /*查询采样数据*/
        DataInfoVo dataInfoVo = DataInfoVo.builder().errorSampling(1).sampling(1).healthTime(assessVo.getHealthTime()).build();
        /*查询子节点*/
        List<NodeTreeInfo> childNode = nodeInfoService.getChildNode(assessVo.getNodeId());
        if(childNode.isEmpty()){
            return CheckResult.fail("该节点无子节点数据");
        }
        /*正常数据查询*/
        Map<String,List<LinkedHashMap<String, Object>>> moduleList = new LinkedHashMap<>(childNode.size());
        for (NodeTreeInfo nodeTreeInfo : childNode) {
            dataInfoVo.setSystemId(nodeTreeInfo.getSystemId());
            dataInfoVo.setNodeId(nodeTreeInfo.getId());
            dataInfoVo.setSatelliteId(nodeTreeInfo.getSatelliteId());
            List<LinkedHashMap<String, Object>> data = bayesService.dataList(dataInfoVo).getData();
            if(CollUtil.isNotEmpty(data)){
                moduleList.put(nodeTreeInfo.getNodeName(),data);
            }

        }
        /*查询异常采样数据*/
        for (NodeTreeInfo nodeTreeInfo : childNode) {
            dataInfoVo.setSystemId(nodeTreeInfo.getSystemId());
            dataInfoVo.setNodeId(nodeTreeInfo.getId());
            dataInfoVo.setSatelliteId(nodeTreeInfo.getSatelliteId());
            List<LinkedHashMap<String, Object>> data1 = bayesService.errorList(dataInfoVo).getData();
            if(CollUtil.isNotEmpty(data1)){
                moduleList.get(nodeTreeInfo.getNodeName()).addAll(data1);
            }
        }
        if(moduleList.isEmpty()){
            return CheckResult.fail("采样无数据");
        }
        assessVo.setModuleList(moduleList);
        /*获取分系统表是哪张表*/
        CheckResult<String> tables = systemTelemetryService.getNodeTelemetryName(assessVo.getSystemId());
        if (tables.no()){
            return CheckResult.fail(tables.getCheckMsg());
        }
        String table = tables.getData();
        /*根据评估时间查询每个节点的状态值*/
        Map<String,Map<String,Object>> paramMap = new LinkedHashMap<>(childNode.size());
        for (NodeTreeInfo nodeTreeInfo : childNode) {
            /*查询节点对应的分系统编号*/
            List<NodeParamInfo> nodeParamInfos = nodeParamInfoService.select(NodeParamInfo.builder().nodeId(nodeTreeInfo.getId()).build());
            if (CollUtil.isNotEmpty(nodeParamInfos)) {
                StringBuilder sb =new StringBuilder();
                nodeParamInfos.forEach(item-> sb.append("`").append(item.getCode()).append("` AS ").append(item.getCode().replace(".","_")).append(","));
                sb.append(" id ");
                /*查询时间点的参数*/
                Map<String,Object> data =  nodeParamInfoMapper.selectParam(NodeInfoServiceImpl.changeSql(sb.toString()) ,assessVo.getHealthTime(),"health_xw."+table,bayesArgs.getNodeCode());
                if(data != null && !data.isEmpty()){
                    Map<String,Object> map = new LinkedHashMap<>();
                    data.forEach((k,v) -> map.put(k.replace("_","."),v));
                    paramMap.put(nodeTreeInfo.getNodeName(),map);
                }
            }
        }
        if(paramMap.isEmpty()){
            return CheckResult.fail(DateUtil.format(assessVo.getHealthTime(),"yyyy-MM-dd HH:mm:ss") +" 的节点参数无数据");
        }
        assessVo.setNodeParams(paramMap);
        /*调用算法*/
        String componentAssessUrl = bayesArgs.getComponentAssessUrl();
        HttpResponse postResponse = HttpUtil.createRequest(Method.POST, componentAssessUrl).body(JSON.toJSONString(assessVo)).execute();
        SystemAssess systemAssess = JSONObject.parseObject(postResponse.body(), SystemAssess.class);
        if(systemAssess.getCode() != 200){
            return  CheckResult.fail(systemAssess.getMsg());
        }
        if(systemAssess.getData() != null){
            String level = HealthStatu.valueof(systemAssess.getData().getPoint());
            systemAssess.getData().setHealthLevel(level);
        }
        return CheckResult.success(systemAssess.getData());
    }

    @Override
    public CheckResult<Object> systemAssess(SystemAssessVo assessVo) {
        List<SystemAssessVo.Weight> weight = assessVo.getWeight();
        if(CollUtil.isEmpty(weight)){
            return CheckResult.fail("权重不能为空");
        }
        long count = weight.stream().filter(f -> {
            String[] split = f.getValue().toString().split("\\.");
            if (split.length > 1) {
                return split[1].length() > 2;
            }
            return false;
        }).count();
        if(count > 0){
            return CheckResult.fail("权重最大保留两位小数");
        }
        int sum = 0;
        for (SystemAssessVo.Weight w : weight) {
            int num = (int)(w.getValue()*100);
            sum+=num;
        }
        if(sum != 100){
            return CheckResult.fail("权重之和必须为1");
        }
        /*查询子节点*/
        List<NodeTreeInfo> childNode = nodeInfoService.getChildNode(assessVo.getNodeId());
        if(childNode.isEmpty()){
            return CheckResult.fail("该节点无子节点数据");
        }
        /*查询分系统下面部件的参数*/
        List<Long> parentIds = childNode.stream().map(NodeTreeInfo::getId).collect(Collectors.toList());
        Example example = new Example(NodeTreeInfo.class);
        example.createCriteria().andIn("parentId",parentIds);
        List<NodeTreeInfo> nodeTreeInfoList = nodeInfoService.selectByExample(example);

        /*查询采样数据*/
        DataInfoVo dataInfoVo = DataInfoVo.builder().errorSampling(1).sampling(1).healthTime(assessVo.getHealthTime()).build();
        Map<String,List<LinkedHashMap<String,Object>>> moduleList = new LinkedHashMap<>(childNode.size());
        for (NodeTreeInfo nodeTreeInfo : nodeTreeInfoList) {
            dataInfoVo.setNodeId(nodeTreeInfo.getId());
            dataInfoVo.setSystemId(nodeTreeInfo.getSystemId());
            dataInfoVo.setSatelliteId(nodeTreeInfo.getSatelliteId());
            List<LinkedHashMap<String, Object>> data = bayesService.dataList(dataInfoVo).getData();
            moduleList.put(nodeTreeInfo.getNodeName(),data);
        }
        /*查询异常采样数据*/
        for (NodeTreeInfo nodeTreeInfo : nodeTreeInfoList) {
            dataInfoVo.setNodeId(nodeTreeInfo.getId());
            dataInfoVo.setSystemId(nodeTreeInfo.getSystemId());
            dataInfoVo.setSatelliteId(nodeTreeInfo.getSatelliteId());
            List<LinkedHashMap<String, Object>> data1 = bayesService.errorList(dataInfoVo).getData();
            moduleList.get(nodeTreeInfo.getNodeName()).addAll(data1);
        }
        if(moduleList.isEmpty()){
            return CheckResult.fail("采样无数据");
        }
        /*处理moduleList 数据*/
        Map<String,Map<String,List<LinkedHashMap<String, Object>>>> moduleLists = new LinkedHashMap<>();
        childNode.forEach(item ->{
            List<String> collect = nodeTreeInfoList.stream().filter(f -> f.getParentId().equals(item.getId())).collect(Collectors.toList()).stream().map(NodeTreeInfo::getNodeName).collect(Collectors.toList());
            Map<String,List<LinkedHashMap<String,Object>>> listMap = new LinkedHashMap<>();
            collect.forEach(col ->{
                if(moduleList.containsKey(col)){
                    List<LinkedHashMap<String, Object>> linkedHashMaps = moduleList.get(col);
                    if(!linkedHashMaps.isEmpty()){
                        listMap.put(col,moduleList.get(col));
                    }
                }
            });
            if(!listMap.isEmpty()){
                moduleLists.put(item.getNodeName(),listMap);
            }
        });
        assessVo.setModuleList(moduleLists);
        List<Long> nodeIds = nodeTreeInfoList.stream().map(NodeTreeInfo::getId).collect(Collectors.toList());
        Example example1 = new Example(NodeParamInfo.class);
        example1.createCriteria().andIn("nodeId",nodeIds);
        List<NodeParamInfo> nodeParamInfos1 = nodeParamInfoService.selectByExample(example1);
        StringBuilder sb =new StringBuilder();
        nodeParamInfos1.forEach(item-> sb.append("`").append(item.getCode()).append("` AS ").append(item.getCode().replace(".","_")).append(","));
        sb.append(" id ");
        /*获取分系统表是哪张表*/
        CheckResult<String> tables = systemTelemetryService.getNodeTelemetryName(assessVo.getSystemId());
        if (tables.no()){
            return CheckResult.fail(tables.getCheckMsg());
        }
        String table = tables.getData();
        Map<String,Object> data =  nodeParamInfoMapper.selectParam(NodeInfoServiceImpl.changeSql(sb.toString()),assessVo.getHealthTime(),"health_xw."+table,"1924293917621092352");
        if(data == null || data.isEmpty()){
            return CheckResult.fail(DateUtil.format(assessVo.getHealthTime(),"yyyy-MM-dd HH:mm:ss") +" 的节点参数无数据");
        }
        Map<String,Object> map = new LinkedHashMap<>();
        data.forEach((k,v) -> map.put(k.replace("_","."),v));
        /*处理节点参数数据*/
        Map<String,Map<String,Object>> stringListMap = new LinkedHashMap<>();
        nodeTreeInfoList.forEach(item ->{
            List<String> collect = nodeParamInfos1.stream().filter(f ->f.getNodeId().equals(item.getId())).collect(Collectors.toList()).stream().map(NodeParamInfo::getCode).collect(Collectors.toList());
            Map<String,Object> tempMap= new LinkedHashMap<>();
            map.forEach((k,v) ->{
                if(collect.contains(k)){
                    tempMap.put(k,v);
                }
            });
            stringListMap.put(item.getNodeName(),tempMap);
        });
        Map<String,Map<String,Map<String,Object>>> paramListMap = new LinkedHashMap<>();
        childNode.forEach(item ->{
            List<String> collect = nodeTreeInfoList.stream().filter(f -> f.getParentId().equals(item.getId())).collect(Collectors.toList()).stream().map(NodeTreeInfo::getNodeName).collect(Collectors.toList());
            Map<String,Map<String,Object>>  mapMap = new LinkedHashMap<>();
            collect.forEach(col ->{
                if(stringListMap.containsKey(col)){
                    Map<String, Object> stringObjectMap = stringListMap.get(col);
                    if(!stringObjectMap.isEmpty()){
                        mapMap.put(col,stringObjectMap);
                    }
                }
            });
            if(!mapMap.isEmpty()){
                paramListMap.put(item.getNodeName(),mapMap);
            }
        });
        if(paramListMap.isEmpty()){
            return CheckResult.fail(DateUtil.format(assessVo.getHealthTime(),"yyyy-MM-dd HH:mm:ss") +" 的节点参数无数据");
        }
        assessVo.setNodeParams(paramListMap);
        /*调用算法*/
        String systemAssessUrl = bayesArgs.getSystemAssessUrl();
        HttpResponse postResponse = HttpUtil.createRequest(Method.POST, systemAssessUrl).body(JSON.toJSONString(assessVo)).execute();
        SystemAssess systemAssess = JSONObject.parseObject(postResponse.body(), SystemAssess.class);
        if(systemAssess.getCode() != 200){
            return  CheckResult.fail(systemAssess.getMsg());
        }
        if(systemAssess.getData() != null){
            String level = HealthStatu.valueof(systemAssess.getData().getPoint());
            systemAssess.getData().setHealthLevel(level);
        }
        return CheckResult.success(systemAssess.getData());
    }
}
